package com.dhl.fin.api.service;

import com.dhl.fin.api.common.exception.BusinessException;
import com.dhl.fin.api.common.service.ExceptionRecordService;
import com.dhl.fin.api.common.util.DateUtil;
import com.dhl.fin.api.common.util.JsonUtil;
import com.dhl.fin.api.common.util.ObjectUtil;
import com.dhl.fin.api.common.util.StringUtil;
import com.dhl.fin.api.constant.ExceptionCodeConstant;
import com.dhl.fin.api.domain.ExtraJobCron;
import com.dhl.fin.api.domain.MensesRemindTask;
import com.dhl.fin.api.domain.RemindTask;
import com.dhl.fin.api.dto.CronJobFunctionParamDTO;
import com.dhl.fin.api.dto.TipMessageDTO;
import com.dhl.fin.api.enums.AutoDealWayEnum;
import com.dhl.fin.api.enums.MensesTypeEnum;
import com.dhl.fin.api.enums.RemindCycleTypeEnum;
import com.dhl.fin.api.enums.RemindTypeEnum;
import com.dhl.fin.api.service.messageService.superService.RemindSendMessageService;
import com.dhl.fin.api.util.CronJobUtil;
import lombok.extern.slf4j.Slf4j;
import org.quartz.CronExpression;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.function.Consumer;

/**
 * @author CuiJianbo
 * @since 2025/5/8
 */
@Slf4j
@Service
public class CronJobService {

    @Autowired
    private RemindTaskService remindTaskService;

    @Autowired
    private MensesRemindTaskService mensesRemindTaskService;

    @Autowired
    private LoginAccountService loginAccountService;

    @Autowired
    private ExtraJobCronService extraJobCronService;

    @Autowired
    private ExceptionRecordService exceptionRecordService;

    @Autowired
    private AbilityServiceCenterService abilityServiceCenterService;


    public String addCronJob(String cronExpress, RemindTask remindTask, ExtraJobCron extraJobCron) {
        Consumer<CronJobFunctionParamDTO> taskFunction = param -> {
            RemindTask task = null;
            ExtraJobCron extraTask = null;
            try {
                task = remindTaskService.get(param.getTaskId(), "remindType");
                extraTask = extraJobCronService.get(param.getExtraJobTaskId());

                if (task.getIsSetEndDate() && ObjectUtil.notNull(task.getEndDate())
                        && task.getEndDate().before(DateUtil.getSysDate())) {
                    endRemindTask(task);
                    return;
                }
                //删除当前定时任务数据
                extraJobCronService.deleteJobById(extraTask.getId());
                //注销当前定时任务
                CronJobUtil.disableCronJob(extraTask.getScheduleIdNum());
                //检查是否为最后一个额外任务
                boolean isLastJob = extraJobCronService.checkIsLastJobOfTask(task.getId(), DateUtil.getFullTime(extraTask.getExecuteTime()));
                if (isLastJob) {
                    CronExpression cron = new CronExpression(task.getCron());
                    Date next = cron.getNextValidTimeAfter(DateUtil.getSysTime());
                    if (task.getRemindCycleWay().equals(RemindCycleTypeEnum.ONE_TIMES.getName())) {
                        if (!next.equals(task.getRemindDateTime())) {
                            endRemindTask(task);
                        }
                    } else {
                        if (task.getIsSetEndDate()) {
                            Date nextDate = task.getNextRemindDateTime(DateUtil.getSysTime());
                            if (nextDate.after(task.getEndDate())) {
                                //如果下一个周期时间超出了结束时间，就结束当前task
                                endRemindTask(task);
                            } else {
                                //一个周期提醒完成，刷新生成下一个周期的提醒任务
                                remindTaskService.freshTaskCronJob(remindTask);
                            }
                        } else {
                            //一个周期提醒完成，刷新生成下一个周期的提醒任务
                            remindTaskService.freshTaskCronJob(remindTask);
                        }
                    }
                }
            } catch (Exception e) {
                exceptionRecordService.addRecordLog("005", "发送提醒失败:" + e.getMessage(), String.format("taskID:%d,ExtraJobCronID:%d", param.getTaskId(), param.getExtraJobTaskId()));
                log.error("发送提醒失败", e);
                return;
            }

            //发送通知消息给用户
            if (task.getIsActive()) {
                RemindTypeEnum remindTypeEnum = RemindTypeEnum.getIconByName(task.getRemindType().getRemindTypeName());
                if (ObjectUtil.isNull(remindTypeEnum)) {
                    remindTypeEnum = RemindTypeEnum.OTHER;
                }
                RemindSendMessageService remindSendMessageService = null;
                try {
                    remindSendMessageService = remindTypeEnum.getMessageTemplateClass()
                            .getConstructor(RemindTask.class, ExtraJobCron.class)
                            .newInstance(task, extraTask);
                } catch (Exception e) {
                    exceptionRecordService.addRecordLog("006", "构造提醒对象失败:" + e.getMessage(), String.format("taskID:%d,ExtraJobCronID:%d", param.getTaskId(), param.getExtraJobTaskId()));
                    throw new BusinessException("构造提醒对象失败");
                }

                TipMessageDTO tipMessageDTO = remindSendMessageService.tipMessage();
                try {
                    //发送订阅消息
                    abilityServiceCenterService.sendSubscribeMsgMiniProgram(tipMessageDTO);
                } catch (Exception e) {
                    if ("给微信用户发送提醒消息失败".equals(e.getMessage())) {
                        loginAccountService.subAllowCount(task.getCreateUser());
                    }
                    return;
                }
                loginAccountService.subAllowCount(task.getCreateUser());

            }

        };

        CronJobFunctionParamDTO paramDto = CronJobFunctionParamDTO.getInstance(remindTask, extraJobCron);

        //注册定时任务
        return CronJobUtil.registerCronJob(cronExpress, paramDto, taskFunction);

    }

    public String addCronJob(String cronExpress, MensesRemindTask mensesRemindTask, ExtraJobCron extraJobCron) {
        Consumer<CronJobFunctionParamDTO> taskFunction = param -> {
            MensesRemindTask task = null;
            ExtraJobCron extraTask = null;
            try {
                task = mensesRemindTaskService.get(param.getMensesTaskId());
                extraTask = extraJobCronService.get(param.getExtraJobTaskId());
                loginAccountService.subAllowCount(task.getCreateUser());
                if (StringUtil.isNotEmpty(extraTask.getRemark()) && extraTask.getRemark().equals(MensesTypeEnum.MENSES_DAY.getName())) {
                    MensesRemindTask data = new MensesRemindTask();
                    data.setId(task.getId());
                    data.setMensesLastDateTwo(task.getMensesLastDateOne());
                    data.setMensesLastDateOne(DateUtil.getSysDate());
                    mensesRemindTaskService.updateBySelective(data);
                }

                //删除额外定时任务数据
                extraJobCronService.deleteJobById(extraTask.getId());
                //注销定时任务
                CronJobUtil.disableCronJob(extraTask.getScheduleIdNum());
                //检查是否为最后一个额外任务
                boolean isLastJob = extraJobCronService.checkIsLastJobOfMensesRemindTask(task.getId(), DateUtil.getFullTime(extraTask.getExecuteTime()));
                if (isLastJob) {
                    extraJobCronService.generateMensesExtraJob(task);
                }

            } catch (Exception e) {
                exceptionRecordService.addRecordLog("007", "发送提醒失败:" + e.getMessage(), String.format("MensesRemindTask ID:%d,ExtraJobCron ID:%d", param.getMensesTaskId(), param.getExtraJobTaskId()));
                log.error("发送提醒失败", e);
                return;
            }

            //发送通知消息给用户
            if (task.getIsActive()) {
                RemindSendMessageService remindSendMessageService = null;
                try {
                    remindSendMessageService = RemindTypeEnum.MENSTRUATION.getMessageTemplateClass()
                            .getConstructor(MensesRemindTask.class, ExtraJobCron.class)
                            .newInstance(task, extraTask);
                } catch (Exception e) {
                    exceptionRecordService.addRecordLog("008", "构造提醒对象失败:" + e.getMessage(), String.format("MensesRemindTask ID:%d,ExtraJobCron ID:%d", param.getMensesTaskId(), param.getExtraJobTaskId()));
                    throw new BusinessException("构造提醒对象失败");
                }

                TipMessageDTO tipMessageDTO = remindSendMessageService.tipMessage();
                try {
                    //发送订阅消息
                    abilityServiceCenterService.sendSubscribeMsgMiniProgram(tipMessageDTO);
                } catch (Exception e) {
                    if ("给微信用户发送提醒消息失败".equals(e.getMessage())) {
                        loginAccountService.subAllowCount(task.getCreateUser());
                    }
                    return;
                }
                loginAccountService.subAllowCount(task.getCreateUser());
            }
        };

        CronJobFunctionParamDTO paramDto = CronJobFunctionParamDTO.getInstance(mensesRemindTask, extraJobCron);

        //注册定时任务
        return CronJobUtil.registerCronJob(cronExpress, paramDto, taskFunction);

    }


    private void endRemindTask(RemindTask task) throws Exception {

        //注销task下的所有定时任务
        extraJobCronService.cancelExtraJob(task.getId());

        if (StringUtil.isNotEmpty(task.getAutoDealWay()) && task.getAutoDealWay().equals(AutoDealWayEnum.DISABLED.getCode())) {
            remindTaskService.updateFieldById(task.getId(), "isActive", false);
        } else {
            remindTaskService.deleteById(task.getId());
        }
    }

}
